﻿#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#define MAX 100

int CurrentCnt = 0;

#define MAX_NAME_LEN 30
#define MAX_PRICE_LEN 30
#define MAX_MANUFACTURER_LEN 30
#define MAX_BRAND_LEN 30

typedef struct node
{
    int goods_id;
    char goods_name[MAX_NAME_LEN + 1];
    char goods_manufacturer[MAX_MANUFACTURER_LEN + 1];
    char goods_brand[MAX_BRAND_LEN + 1];
    int goods_price;
    double goods_discount;
    int goods_amount;
    int goods_remain;
    struct node* next;
} GoodsList;

void info_init(GoodsList**);
void print_all(GoodsList*);
void Destory(GoodsList**);
void Delete(GoodsList**);
void info_change(GoodsList*);
void Print_Goodinfo(GoodsList*);
void search(GoodsList*);
void info_insert(GoodsList**);
void Del_one(GoodsList**);
void save(GoodsList*);
void sort_goods(GoodsList**);
void exchange_node(GoodsList*, GoodsList*);
void sell(GoodsList*);

int main(void)
{
    char cmd, choose;
    GoodsList* lib = NULL;
    info_init(&lib);
    while (1)
    {
        printf("\n              超市商品管理系统\n");
        printf("********************************************\n");
        printf("1.显示所有商品信息\n");
        printf("2.修改某个商品信息\n");
        printf("3.插入某个商品信息\n");
        printf("4.删除某个商品信息\n");
        printf("5.查找某个商品信息\n");
        printf("6.商品存盘并退出系统\n");
        printf("7.统计商品信息\n");
        printf("8.删除所有内容（慎用）\n");
        printf("9.购买商品\n");
        printf("0.不存盘退出系统\n");
        printf("********************************************\n");
        printf("输入您的选择: ");
        scanf("%c", &cmd);
        getchar();
        switch (cmd)
        {
        case '1':
            print_all(lib);
            break;
        case '2':
            info_change(lib);
            break;
        case '3':
            info_insert(&lib);
            break;
        case '4':
            Del_one(&lib);
            break;
        case '5':
            search(lib);
            break;
        case '6':
            save(lib);
            Destory(&lib);
            printf("存盘完成，按任意键退出...\n");
            system("pause >nul");
            return 0;
        case '7':
            sort_goods(&lib);
            break;
        case '8':
            Delete(&lib);
            break;
        case '9':
            sell(lib);
            break;
        case '0':
            while (1)
            {
                printf("商品链表未保存，修改内容将会全部丢失，是否退出？(Y/N)\n");
                scanf("%c", &choose);
                getchar();
                if (choose == 'Y' || choose == 'y')
                {
                    Destory(&lib);
                    return 0;
                }
                else if (choose == 'N' || choose == 'n')
                    break;
                else
                {
                    printf("输入错误，请重新输入(Y/N):\n");
                }
            }
            break;
        default:
            printf("输入错误，请重新选择\n");
            break;
        }
        system("pause");
        system("CLS");
    }
}

void info_init(GoodsList** first)
{
    FILE* fp = NULL;
    int num = 0, flag = 0;
    GoodsList cache, * new_node, * cur = NULL;
    fopen_s(&fp, "goodsinfo.txt", "r");
    if (fp == NULL)
    {
        printf("商品信息文件不存在！链表为空！将为您新建一个。\n");
        fopen_s(&fp, "goodsinfo.txt", "w");
        fclose(fp);
        *first = NULL;
        return;
    }
    else
    {
        while (
            fscanf(fp, "%d%s%s%s%d%lf%d%d", &cache.goods_id, &cache.goods_name, &cache.goods_manufacturer, &cache.goods_brand, &cache.goods_price, &cache.goods_discount, &cache.goods_amount, &cache.goods_remain) != EOF)
        {
            new_node = (GoodsList*)malloc(sizeof(GoodsList));
            if (new_node == NULL)
            {
                printf("系统内存空间不足！无法创建链表！\n");
                printf("请留出足够内存后启动程序\n");
                system("pause");
                exit(1);
            }
            *new_node = cache;
            new_node->next = NULL;
            if (flag == 0)
            {
                *first = new_node;
                flag = 1;
                cur = new_node;
            }
            else
            {
                cur->next = new_node;
                cur = cur->next;
            }
            num++;
        }
    }
    CurrentCnt = num;
    printf("商品链表文件已建立，有%d个商品记录\n", num);
    fclose(fp);
}

void print_all(GoodsList* first)
{
    GoodsList* cur;
    for (
        cur = first;
        cur != NULL;
        cur = cur->next)
    {
        printf("\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
        printf("ID:%-8d名称:%s\t生产厂家:%s\t品牌:%s\t价格:%-8d折扣:%-8g数量:%-8d剩余:%-d\n",
            cur->goods_id, cur->goods_name, cur->goods_manufacturer, cur->goods_brand, cur->goods_price, cur->goods_discount, cur->goods_amount, cur->goods_remain);
        printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
    }
}

void Destory(GoodsList** first)
{
    GoodsList* pre, * cur;
    for (
        pre = NULL, cur = *first;
        cur != NULL;
        pre = cur, cur = cur->next)
    {
        if (pre != NULL)
        {
            free(pre);
        }
    }
    if (pre != NULL)
    {
        free(pre);
    }
    *first = NULL;
    CurrentCnt = 0;
}

void Delete(GoodsList** first)
{
    char choose;
    FILE* fp = NULL;
    while (1)
    {
        printf("您即将清空所有数据，此操作将不可逆，是否确定？(Y/N)\n");
        scanf("%c", &choose);
        getchar();
        if (choose == 'Y' || choose == 'y')
        {
            Destory(first);
            fopen_s(&fp, "goodsinfo.txt", "w");
            fclose(fp);
            return;
        }
        else if (choose == 'N' || choose == 'n')
        {
            printf("操作取消！\n");
            break;
        }
        else
        {
            printf("输入错误，请重新输入(Y/N):\n");
        }
    }
}

void Print_Goodinfo(GoodsList* cur)
{
    printf("\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
    printf("ID:%-8d名称:%s\t生产厂家:%s\t品牌:%s\t价格:%-8d折扣:%-8g数量:%-8d剩余:%-d\n",
        cur->goods_id, cur->goods_name, cur->goods_manufacturer, cur->goods_brand, cur->goods_price, cur->goods_discount, cur->goods_amount, cur->goods_remain);
    printf("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
}

void info_change(GoodsList* first)
{
    GoodsList* cur;
    char name[MAX_NAME_LEN + 1];
    printf("请输入需要修改的商品名称: \n");
    scanf("%s", name);
    getchar();
    for (
        cur = first;
        cur != NULL && strcmp(cur->goods_name, name) != 0;
        cur = cur->next)
        ;
    if (cur == NULL)
    {
        printf("商品信息未找到！\n");
        return;
    }
    else
    {
        Print_Goodinfo(cur);
        printf("请输入新的商品信息： \n");
        printf("商品ID：");
        scanf("%d", &cur->goods_id);
        printf("商品名称：");
        scanf("%s", cur->goods_name);
        printf("商品生产厂家：");
        scanf("%s", cur->goods_manufacturer);
        printf("商品品牌：");
        scanf("%s", cur->goods_brand);
        printf("商品价格：");
        scanf("%d", &cur->goods_price);
        printf("商品折扣：");
        scanf("%lf", &cur->goods_discount);
        printf("商品数量：");
        scanf("%d", &cur->goods_amount);
        printf("商品剩余：");
        scanf("%d", &cur->goods_remain);
        getchar();
        printf("修改商品信息成功！修改后信息为：\n");
        Print_Goodinfo(cur);
    }
}

void search(GoodsList* first)
{
    GoodsList* cur;
    char name[MAX_NAME_LEN + 1];
    printf("请输入需要查找的商品名称: \n");
    scanf("%s", name);
    getchar();
    for (
        cur = first;
        cur != NULL && strcmp(cur->goods_name, name) != 0;
        cur = cur->next)
        ;
    if (cur == NULL)
    {
        printf("商品信息未找到！\n");
        return;
    }
    else
    {
        Print_Goodinfo(cur);
    }
}

void info_insert(GoodsList** first)
{
    GoodsList* pre, * cur, * new_node;
    int cmd, i;
    new_node = (GoodsList*)malloc(sizeof(GoodsList));
    if (new_node == NULL)
    {
        printf("系统内存空间不足！无法创建链表！\n");
        printf("请留出足够内存后启动程序\n");
        system("pause");
        exit(1);
    }
    else
    {
        printf("请输入你要插入的商品信息： \n");
        printf("商品ID：");
        scanf("%d", &new_node->goods_id);
        printf("商品名称：");
        scanf("%s", new_node->goods_name);
        printf("商品生产厂家：");
        scanf("%s", new_node->goods_manufacturer);
        printf("商品品牌：");
        scanf("%s", new_node->goods_brand);
        printf("商品价格：");
        scanf("%d", &new_node->goods_price);
        printf("商品折扣：");
        scanf("%lf", &new_node->goods_discount);
        printf("商品数量：");
        scanf("%d", &new_node->goods_amount);
        printf("商品剩余：");
        scanf("%d", &new_node->goods_remain);
        getchar();

        for (
            cur = *first;
            cur != NULL && cur->goods_id != new_node->goods_id;
            cur = cur->next)
            ;
        if (cur == NULL)
        {
            printf("输入数字表明你要插入的位置: \n");
            printf("(0.商品列表尾部\t1.商品列表头部\ti.商品列表中间第i个位置)\n");
            printf("请输入: ");
            scanf("%d", &cmd);
            getchar();
            if (cmd == 1)
            {
                new_node->next = *first;
                *first = new_node;
            }
            else if (cmd == 0)
            {
                for (
                    pre = NULL, cur = *first;
                    cur != NULL;
                    pre = cur, cur = cur->next)
                    ;
                if (pre == NULL)
                {
                    new_node->next = NULL;
                    *first = new_node;
                }
                else
                {
                    new_node->next = NULL;
                    pre->next = new_node;
                }
            }
            else
            {
                if (CurrentCnt <= cmd)
                    printf("位置大于商品列表总数，将为您插入商品列表尾部\n");
                for (
                    pre = NULL, cur = *first, i = 1;
                    cur != NULL && i < cmd;
                    pre = cur, cur = cur->next, i++)
                    ;
                if (pre == NULL)
                {
                    new_node->next = NULL;
                    *first = new_node;
                }
                else
                {
                    pre->next = new_node;
                    new_node->next = cur;
                }
            }
            CurrentCnt++;
            printf("插入商品信息成功！插入的信息为：\n");
            Print_Goodinfo(new_node);
        }
        else
        {
            printf("待插入的商品ID已存在！\n");
            free(new_node);
        }
    }
}

void Del_one(GoodsList** first)
{
    GoodsList* pre, * cur;
    char name[MAX_NAME_LEN + 1], choose;
    printf("请输入需要删除的商品名称: \n");
    scanf("%s", name);
    getchar();
    for (
        pre = NULL, cur = *first;
        cur != NULL && strcmp(cur->goods_name, name) != 0;
        pre = cur, cur = cur->next)
        ;
    if (cur == NULL)
    {
        printf("商品信息未找到！\n");
        return;
    }
    else
    {

        printf("请确认您将要删除的商品信息: \n");
        Print_Goodinfo(cur);
        while (1)
        {
            printf("是否确认删除？(Y/N)\n");
            choose = getchar();
            getchar();
            if (choose == 'y' || choose == 'Y')
            {
                if (pre == NULL)
                {
                    *first = cur->next;
                    free(cur);
                }
                else
                {
                    pre->next = cur->next;
                    free(cur);
                }
                CurrentCnt--;
                printf("删除成功！\n");
                return;
            }
            else if (choose == 'N' || choose == 'n')
            {
                printf("操作取消\n");
                return;
            }
            else
            {
                printf("输入错误，请重新输入(Y/N):\n");
            }
        }
    }
}

void save(GoodsList* first)
{
    FILE* fp;
    GoodsList* cur;
    fopen_s(&fp, "goodsinfo.txt", "w");
    for (
        cur = first;
        cur != NULL;
        cur = cur->next)
    {
        fprintf(fp, "%-d\t%s\t%s\t%s\t%-d\t%-g\t%-d\t%-d\n",
            cur->goods_id, cur->goods_name, cur->goods_manufacturer, cur->goods_brand, cur->goods_price, cur->goods_discount, cur->goods_amount, cur->goods_remain);
    }
    fclose(fp);
}

void sell(GoodsList* first)
{
    char category[MAX_NAME_LEN + 1], name[MAX_NAME_LEN + 1];
    int amount;
    GoodsList* cur;
    printf("请输入商品名称: ");
    scanf("%s", name);
    printf("请输入购买数量: ");
    scanf("%d", &amount);
    getchar();

    for (cur = first; cur != NULL; cur = cur->next)
    {
        if (strcmp(cur->goods_name, name) == 0 && cur->goods_remain >= amount)
        {
            printf("购买成功！购买的商品信息为：\n");
            Print_Goodinfo(cur);
            cur->goods_remain -= amount;
            return;
        }
        else if (strcmp(cur->goods_name, name) == 0)
        {
            printf("库存不够，无法购买该商品！\n");
            return;
        }
    }
    printf("没有找到该商品！\n");
    return;
}

void sort_price_asc(GoodsList** list)
{
    GoodsList* pre, * cur;
    int i;
    for (i = 1; i < CurrentCnt; i++)
    {
        for (
            pre = NULL, cur = *list;
            cur->next != NULL;
            pre = cur, cur = cur->next)
        {
            if (cur->next == NULL)
                break;
            if (cur->goods_price > (cur->next)->goods_price)
            {
                exchange_node(cur, cur->next);
            }
        }
    }
    printf("按照价格升序排序完成\n");
}

void sort_remain_desc(GoodsList** list)
{
    GoodsList* pre, * cur;
    int i;
    for (i = 1; i < CurrentCnt; i++)
    {
        for (
            pre = NULL, cur = *list;
            cur->next != NULL;
            pre = cur, cur = cur->next)
        {
            if (cur->next == NULL)
                break;
            if (cur->goods_remain < (cur->next)->goods_remain)
            {
                exchange_node(cur, cur->next);
            }
        }
    }
    printf("按照剩余数量降序排序完成\n");
}

void sort_name_asc(GoodsList** list)
{
    GoodsList* pre, * cur;
    int i;
    for (i = 1; i < CurrentCnt; i++)
    {
        for (
            pre = NULL, cur = *list;
            cur->next != NULL;
            pre = cur, cur = cur->next)
        {
            if (cur->next == NULL)
                break;
            if (strcmp(cur->goods_name, (cur->next)->goods_name) > 0)
            {
                exchange_node(cur, cur->next);
            }
        }
    }
    printf("按照商品名称首字母升序排序完成\n");
}

void sort_manufacturer_list(GoodsList** list)
{
    GoodsList* pre, * cur;
    int i;
    for (i = 1; i < CurrentCnt; i++)
    {
        for (
            pre = NULL, cur = *list;
            cur->next != NULL;
            pre = cur, cur = cur->next)
        {
            if (cur->next == NULL)
                break;
            if (strcmp(cur->goods_manufacturer, (cur->next)->goods_manufacturer) > 0)
            {
                exchange_node(cur, cur->next);
            }
        }
    }
}

void sort_brand_list(GoodsList** list)
{
    GoodsList* pre, * cur;
    int i;
    for (i = 1; i < CurrentCnt; i++)
    {
        for (
            pre = NULL, cur = *list;
            cur->next != NULL;
            pre = cur, cur = cur->next)
        {
            if (cur->next == NULL)
                break;
            if (strcmp(cur->goods_brand, (cur->next)->goods_brand) > 0)
            {
                exchange_node(cur, cur->next);
            }
        }
    }
}

void sort_manufacturer(GoodsList* first)
{
    GoodsList* cur;
    char pre_manufacturer[MAX_MANUFACTURER_LEN + 1] = "";
    sort_manufacturer_list(&first);
    for (
        cur = first;
        cur != NULL;
        cur = cur->next)
    {
        if (strcmp(cur->goods_manufacturer, pre_manufacturer) != 0)
        {
            printf("\n\n-----------------------生产厂家：%s-----------------------\n\n", cur->goods_manufacturer);
        }
        Print_Goodinfo(cur);
        strcpy(pre_manufacturer, cur->goods_manufacturer);
    }
}

void sort_brand(GoodsList* first)
{
    GoodsList* cur;
    char pre_brand[MAX_BRAND_LEN + 1] = "";
    sort_brand_list(&first);
    for (
        cur = first;
        cur != NULL;
        cur = cur->next)
    {
        if (strcmp(cur->goods_brand, pre_brand) != 0)
        {
            printf("\n\n-----------------------品牌：%s-----------------------\n\n", cur->goods_brand);
        }
        Print_Goodinfo(cur);
        strcpy(pre_brand, cur->goods_brand);
    }
}

void exchange_node(GoodsList* one, GoodsList* two)
{
    GoodsList cache, * one_next, * two_next;
    cache = *two;
    one_next = one->next;
    two_next = two->next;
    *two = *one;
    two->next = two_next;
    *one = cache;
    one->next = one_next;
}

void sort_goods(GoodsList** list)
{
    char choose;
    printf("1.按照价格升序排序\n");
    printf("2.按照剩余数量降序排序\n");
    printf("3.按照商品名称首字母升序排序\n");
    printf("4.按照生产厂家分类显示\n");
    printf("5.按照品牌分类显示\n");
    printf("请输入您的选择: ");
    scanf("%c", &choose);
    getchar();
    switch (choose)
    {
    case '1':
        sort_price_asc(list);
        break;
    case '2':
        sort_remain_desc(list);
        break;
    case '3':
        sort_name_asc(list);
        break;
    case '4':
        sort_manufacturer(*list);
        break;
    case '5':
        sort_brand(*list);
        break;
    default:
        printf("输入错误，请重新选择\n");
        break;
    }
}